#pragma once

#include <compl.h>
#include <dbg.h>

#include <dinfra/init_fin.h>
#include <metalc/base/mreq.h>

typedef void *(perm_allocf_t)(size_t size);
/* 锁预留空间 */
// #define MLAYER_SYNC_SPACE(SIZE)		char __lock_reserved[SIZE < HDEF_CACHE_LINE_BYTES ? HDEF_CACHE_LINE_BYTES : align_up(SIZE, HDEF_CACHE_LINE_BYTES)]
// #define MLAYER_SYNC_SPACE(SIZE)		char __lock_reserved[SIZE]
// #define MLAYER_GETLOCK(obj)			&((obj)->__lock_reserved[0])
#define MLAYER_SYNC_TYPE(lock)			lock##_t
// #define MLAYER_SYNC_SIZE(lock)		(sizeof(EXPAND(DEFER(MLAYER_SYNC_TYPE)(lock))))
#define MLAYER_SYNC(layername, lock)		typedef EXPAND(DEFER(MLAYER_SYNC_TYPE)(lock)) layername##_apds_t; static const OUFUN_TYPE(apds) *layername##_apds_fun = OUFUN_OF(lock);
#define MLAYER_APDS_INIT(name, ...) 		EXPAND(DEFER(__MCAT)(name, _init)) (__VA_ARGS__)
#define MLAYER_APDS_SYNC(name, ...) 		EXPAND(DEFER(__MCAT)(name, _sync)) (__VA_ARGS__)


/* 不超过这个 */
#define MLAYER_SZ_MAXBIT			HDEF_PTR_BITS
#define MLAYER_IS_LASTLAYER(cont)		(!((cont)->lmaxsize < (size_t)BIT(MLAYER_SZ_MAXBIT)))
#define MLAYER_INVALID_REQSZ(cont, rqsz)	(((cont)->lmaxsize < (size_t)BIT(MLAYER_SZ_MAXBIT)) && ((rqsz) >= (cont)->lmaxsize))
#define __MLAYER_INVALID_REQSZ(maxsz, rqsz)	(UNLIKELY(((maxsz < (size_t)BIT(MLAYER_SZ_MAXBIT)) && ((rqsz) > maxsz))))

#define MLAYER_GET_OBJ(mtls, cont)		((mtls)->objs[(cont)->lidx])			

#define DEF_MLFUNC(name, flsizeof, flalloc, flfree, flidx, flmaxsize)  \
static const mlfunc_t name##_mlfunc = { .lsizeof = flsizeof, .lalloc = flalloc , .lfree = flfree, .lidx = flidx, .lmaxsize = flmaxsize };

/* 定义layer层级函数和layer层级函数的连接 */
#define DECL_MLAYER_FUNC(lname)\
SAI void   lname##_pinit(const mlfunc_t * cont);\
SAI void   lname##_tinit(const mlfunc_t * cont);\
SAI size_t lname##_sizeof(mreq_t *req, const mlfunc_t * cont);\
SAI void   *lname##_alloc(mreq_t *req, const mlfunc_t * cont);\
SAI bool_t lname##_free(mreq_t *req, const mlfunc_t * cont);

#define DECL_MLAYER_COMPFUNC(lname)\
SAI size_t lname##_sizeof_comp(mreq_t *req);\
SAI void   *lname##_alloc_comp(mreq_t *req);\
SAI bool_t lname##_free_comp(mreq_t *req);


#define GET_MLAYER_OBJNR(name)		  name##_mlayer_objnr	
#define DEF_MLAYER_OBJNR(name, nr)	  static const size_t GET_MLAYER_OBJNR(name) = nr;

#define GET_MLAYER_MAXSZ(name)		  name##_mlayer_max_allocate_size 
#define DEF_MLAYER_MAXSZ(name, sz)	  static const size_t GET_MLAYER_MAXSZ(name) = sz;


/* 能管理到最大 */
#define DEF_MLOS(name, objnr)\
DECL_MLAYER_FUNC(name)\
DEF_MLAYER_MAXSZ(name, -1)\
DEF_MLAYER_OBJNR(name, objnr)

#define DEF_MLAYER_BASIC(name, size_max, objnr)\
DECL_MLAYER_FUNC(name)\
DEF_MLAYER_MAXSZ(name, size_max)\
DEF_MLAYER_OBJNR(name, objnr)


/* objnr应该是求和方式获得 */
#define __SUM_MLAYER_OBJNR(l)			GET_MLAYER_OBJNR(l) +
#define SUM_MLAYER_OBJNR(...)			MAP(__SUM_MLAYER_OBJNR, __VA_ARGS__) + 0

/* 连接两层 */
#define CONNECT_MLAYER(unlinkedl1, l2)\
DECL_MLAYER_COMPFUNC(l2) /* 先声明 */\
static const size_t l2##_lidx__ = unlinkedl1##_lidx__ + GET_MLAYER_OBJNR(unlinkedl1);\
DEF_MLFUNC(unlinkedl1, l2##_sizeof_comp, l2##_alloc_comp, l2##_free_comp, unlinkedl1##_lidx__, GET_MLAYER_MAXSZ(unlinkedl1))\
SYSINIT_FUNC(unlinkedl1){ unlinkedl1##_pinit(&unlinkedl1##_mlfunc); }\
CFLOWINIT_FUNC(unlinkedl1){  unlinkedl1##_tinit(&unlinkedl1##_mlfunc); }\
SAI size_t unlinkedl1##_sizeof_comp(mreq_t *req){ return unlinkedl1##_sizeof(req, &unlinkedl1##_mlfunc); }\
SAI void *unlinkedl1##_alloc_comp(mreq_t *req){ return unlinkedl1##_alloc(req, &unlinkedl1##_mlfunc);}\
SAI bool_t unlinkedl1##_free_comp(mreq_t *req){ return unlinkedl1##_free(req, &unlinkedl1##_mlfunc);}


/* 设置一个id什么也不做 */
#define MSIZEOF_ERR	 ((size_t)0)

/* 最后一个需要连接的id层 */
SYSINIT_FUNC(id){ }
CFLOWINIT_FUNC(id){ }
SAI void __CONNECTED_FUNC(sysinit, id)(){ }
SAI void __CONNECTED_FUNC(cflowinit, id)(){ }

SAI size_t id_sizeof_comp(mreq_t *req){
	PARAM_USED(req);
	return MSIZEOF_ERR;
}
SAI void *id_alloc_comp(mreq_t *req){
	PARAM_USED(req);
	return NULL_PTR;
}
SAI bool_t id_free_comp(mreq_t *req){
	PARAM_USED(req);
	return FALSE;
}

/* 定义新mlayer
	- name, 新mlayer的名字
	- ... 多个mlayer
*/
#define COMPOSE_MLAYER(name, ...) \
static const size_t EXPAND(DEFER(__MCAT)(HD(__VA_ARGS__),_lidx__)) = 0;	\
DEF_MLAYER_OBJNR(name, SUM_MLAYER_OBJNR(__VA_ARGS__)) /* 所有之和 */	\
MAPL(CONNECT_MLAYER, GEN_PAIRLIST(__VA_ARGS__, id))			\
MAPL(__SYSINIT_COMPOSE, GEN_PAIRLIST(__VA_ARGS__, __omega)) /* 组合 */	\
MAPL(__CFLOWINIT_COMPOSE, GEN_PAIRLIST(__VA_ARGS__, __omega))		\
SYSINIT_FUNC(name){ EXPAND(DEFER(__MCAT) (HD(__VA_ARGS__, __omega), _sysinit()) ); }		\
CFLOWINIT_FUNC(name){ EXPAND(DEFER(__MCAT) (HD(__VA_ARGS__, __omega), _cflowinit()) );  }	\
SAI size_t name##_sizeof(mreq_t *req){ return EXPAND(DEFER(__MCAT) ( HD(__VA_ARGS__), _sizeof_comp)) (req); }\
SAI void *name##_alloc(mreq_t *req){ return EXPAND(DEFER(__MCAT) ( HD(__VA_ARGS__), _alloc_comp)) (req); }\
SAI bool_t name##_free(mreq_t *req){ return EXPAND(DEFER(__MCAT) ( HD(__VA_ARGS__), _free_comp)) (req); }


// #define COMPOSE_MLAYER(name, ...) \
// static const size_t EVAL(DEFER(__MCAT)(HD(__VA_ARGS__),_lidx__)) = 0;	\
// DECL_INIT(name)								\
// DEF_MLAYER_OBJNR(name, SUM_MLAYER_OBJNR(__VA_ARGS__)) /* 所有之和 */	\
// MAPL(CONNECT_MLAYER, GEN_PAIRLIST(__VA_ARGS__, id))			\
// CONNECT_PROCINIT(__VA_ARGS__, id)					\
// CONNECT_THREADINIT(__VA_ARGS__, id)					\
// SAI void   name##_procinit(){  __PROC_INIT_FUNC( HD(__VA_ARGS__) ) (); }\
// SAI void   name##_threadinit(){  __THREAD_INIT_FUNC( HD(__VA_ARGS__) ) (); }\
// SAI size_t name##_sizeof(mreq_t *req){ return EVAL(DEFER(__MCAT)(HD(__VA_ARGS__),_sizeof_comp)) (req); }\
// SAI void   *name##_alloc(mreq_t *req){ return EVAL(DEFER(__MCAT)(HD(__VA_ARGS__),_alloc_comp)) (req); }\
// SAI bool_t name##_free(mreq_t *req){ return EVAL(DEFER(__MCAT)(HD(__VA_ARGS__),_free_comp)) (req); }

